package com.wei.czz.framework.blog.manager;

import com.wei.czz.common.dto.blog.comment.CommentDto;
import com.wei.czz.common.enums.blog.BlogUserOperationEnum;
import com.wei.czz.common.enums.blog.comment.CommentEnum;
import com.wei.czz.common.enums.CommonEnum;
import com.wei.czz.common.enums.ResultEnum;
import com.wei.czz.common.enums.common.exportTask.ExportStatusEnum;
import com.wei.czz.common.enums.rabbitMQ.BlogCommentMessageEnum;
import com.wei.czz.common.enums.rabbitMQ.MqEnum;
import com.wei.czz.common.exception.CzzException;
import com.wei.czz.common.po.UserPo;
import com.wei.czz.common.tool.PageDto;
import com.wei.czz.common.utils.SecurityUtils;
import com.wei.czz.common.vo.blog.BlogCommentVo;
import com.wei.czz.common.vo.blog.comment.CommentFormVo;
import com.wei.czz.framework.admin.entity.UserEntity;
import com.wei.czz.framework.admin.helper.UserHelper;
import com.wei.czz.framework.blog.entity.BlogCommentEntity;
import com.wei.czz.framework.blog.entity.BlogEntity;
import com.wei.czz.framework.blog.helper.BlogCommentHelper;
import com.wei.czz.framework.blog.service.BlogCommentService;
import com.wei.czz.framework.blog.service.BlogIssueService;
import com.wei.czz.framework.blog.service.BlogService;
import com.wei.czz.framework.common.entity.ExportTaskEntity;
import com.wei.czz.framework.common.helper.RabbitHelper;
import com.wei.czz.framework.common.service.ExportTaskService;
import com.wei.czz.framework.index.service.UserLikeCommentService;
import com.wei.czz.framework.rabbitMQ.message.blog.BlogCommentMessage;
import com.wei.czz.framework.rabbitMQ.message.blog.BlogOperationMessage;
import lombok.AllArgsConstructor;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Component;
import org.springframework.transaction.annotation.Transactional;

import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.util.*;
import java.util.stream.Collectors;

/**
 * Created by IntelliJ IDEA.
 *
 * @author wyw
 * date: 2023-12-06 15:27:38
 * className: BlogCommentManager
 * version: 1.0
 * description:
 */
@Component
@AllArgsConstructor
public class BlogCommentManager {

    private static final Logger log = LoggerFactory.getLogger(BlogCommentManager.class);

    private final BlogService blogService;

    private final BlogCommentService blogCommentService;

    private final BlogIssueService blogIssueService;

    private final UserLikeCommentService userLikeCommentService;

    private final ExportTaskService exportTaskService;

    private final UserHelper userHelper;

    private final RabbitHelper rabbitHelper;

    private final BlogCommentHelper blogCommentHelper;

    @Transactional
    public void saveComment(BlogCommentVo blogCommentVo) {
        UserPo userPo = SecurityUtils.getUser();

        /*
            判断博客是否存在
         */
        blogIssueService.existBlog(blogCommentVo.getBlogId());

        /*
            保存博客评论
         */
        Long commentId = blogCommentService.saveComment(blogCommentVo);

        // 博客作者是否点赞评论
        boolean authorLikeFlag = blogCommentVo.getAuthorLike().equals(CommentEnum.AUTHOR_LIKE.getValue());
        if (authorLikeFlag) {
            /*
                作者点赞该评论
             */
            userLikeCommentService.saveUserLikeComment(blogCommentVo.getBlogId(), commentId);
        }

        /*
            发送消息
         */
        BlogOperationMessage blogOperationMessage = new BlogOperationMessage();
        // 设置博客id、操作的用户id、操作类型（`用户评论`）和变化值和评论区块id属性值
        blogOperationMessage.setBlogId(blogCommentVo.getBlogId())
                .setUpdateUserId(userPo.getUserId())
                .setOptType(BlogUserOperationEnum.COMMENT_OPT.getValue())
                .setNum(1)
                .setBlockId(Objects.isNull(blogCommentVo.getBlockId()) ? null : blogCommentVo.getBlockId());
        // 发送一条消息到MQ中，异步更新’系统博客的被评论数量‘和‘被回复评论的被回复数量’
        rabbitHelper.send(MqEnum.BLOG_COMMENT, blogOperationMessage);
    }

    public CommentDto saveOneComment(BlogCommentVo blogCommentVo) {
        Long optUserId = SecurityUtils.getUserId();

        /*
            判断博客是否存在
         */
        blogIssueService.existBlog(blogCommentVo.getBlogId());

        /*
            保存博客评论
         */
        CommentDto commentDto = blogCommentService.saveOneComment(blogCommentVo);

        /*
            发送消息
         */
        BlogOperationMessage blogOperationMessage = new BlogOperationMessage();
        // 设置博客id、操作的用户id、操作类型（`用户评论`）和变化值属性值
        blogOperationMessage.setBlogId(blogCommentVo.getBlogId())
                .setUpdateUserId(optUserId)
                .setOptType(BlogUserOperationEnum.COMMENT_OPT.getValue())
                .setNum(CommonEnum.ONE.getValue());
        // 发送一条消息到MQ中，异步更新系统博客的被评论数量
        rabbitHelper.send(MqEnum.BLOG_COMMENT, blogOperationMessage);

        return commentDto;
    }

    @Transactional
    public List<CommentDto> saveChildComment(BlogCommentVo blogCommentVo) {
        Long optUserId = SecurityUtils.getUserId();
        UserPo userPo = SecurityUtils.getUser();

        /*
            判断博客是否存在
         */
        blogIssueService.existBlog(blogCommentVo.getBlogId());

        CommentDto commentDto = blogCommentService.saveChildComment(blogCommentVo);

        List<CommentDto> commentDtoList = new ArrayList<>();
        if (blogCommentVo.getPage() != null || blogCommentVo.getLimit() != null
                || StringUtils.isNotBlank(blogCommentVo.getField()) || StringUtils.isNotBlank(blogCommentVo.getOrder())) {
            // 查询博客子评论列表
            commentDtoList = blogCommentService.getChildrenCommentList(blogCommentVo);
        }

        if (userPo.getUserId().equals(blogCommentVo.getParentUserId())) {
            /*
                如果用户自己回复自己
             */
            // 设置被评论的用户名称
            commentDto.setParentUserName(userPo.getUsername());
        } else {
            UserEntity parentUser = userHelper.get(blogCommentVo.getParentUserId());
            // 设置被评论的用户名称
            commentDto.setParentUserName(parentUser.getUsername());
        }

        // 移除列表中与刚添加评论id相同id的评论信息
        commentDtoList = commentDtoList.stream()
                .filter(commentDto1 -> !commentDto1.getCommentId().equals(commentDto.getCommentId()))
                .collect(Collectors.toList());
        // 将最新评论信息放到评论列表头部
        commentDtoList.add(0, commentDto);


        /*
            发送消息
         */
        BlogOperationMessage blogOperationMessage = new BlogOperationMessage();
        // 设置博客id、操作的用户id、操作类型（`用户评论`）和变化值和评论区块id属性值
        blogOperationMessage.setBlogId(blogCommentVo.getBlogId())
                .setUpdateUserId(optUserId)
                .setOptType(BlogUserOperationEnum.COMMENT_OPT.getValue())
                .setNum(CommonEnum.ONE.getValue())
                .setBlockId(blogCommentVo.getBlockId());
        // 发送一条消息到MQ中，异步更新’系统博客的被评论数量‘和‘被回复评论的被回复数量’
        rabbitHelper.send(MqEnum.BLOG_COMMENT, blogOperationMessage);


        return commentDtoList;
    }

    public PageDto<CommentDto> getCommentList(CommentFormVo commentFormVo) {
        return blogCommentService.getCommentList(commentFormVo);
    }

    public PageDto<CommentDto> getOneCommentList(BlogCommentVo blogCommentVo) {
        return blogCommentService.getOneCommentList(blogCommentVo);
    }

    public List<CommentDto> getChildrenCommentList(BlogCommentVo blogCommentVo) {
        return blogCommentService.getChildrenCommentList(blogCommentVo);
    }

    public CommentDto getCommentInfo(Long commentId) {
        /*
            获取博客评论
         */
        BlogCommentEntity blogComment = blogCommentService.getCommentInfo(commentId);

        /*
            获取评论用户
         */
        UserEntity user = userHelper.get(blogComment.getUserId());

        CommentDto commentDto = new CommentDto();
        // 设置评论用户名称
        commentDto.setUserName(user.getUsername());
        if (!blogComment.getParentUserId().equals(CommonEnum.ZERO.getLongValue())) {
            /*
                被评论用户id不为0，则该评论为回复评论，查询被评论用户的名称
             */
            user = userHelper.get(blogComment.getParentUserId());
            // 设置被回复评论的用户名称
            commentDto.setParentUserName(user.getUsername());

            BlogCommentEntity parentBlogComment = blogCommentService.getCommentInfo(blogComment.getParentCommentId());

            // 设置被回复评论内容
            commentDto.setContent(parentBlogComment.getContent());
        }
        return commentDto;
    }

    public void blogCommentChoiceExport(Long taskId, HttpServletResponse response) {
        // 获取请求用户
        UserPo userPo = SecurityUtils.getUser();
        Date start = new Date();

        /*
            获取导出任务
         */
        ExportTaskEntity exportTask = exportTaskService.get(taskId);
        if (!ExportStatusEnum.ACTIVITY.getValue().equals(exportTask.getStatus())) {
            log.info("任务状态不对：status={}", ExportStatusEnum.getName(exportTask.getStatus()));
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "博客评论导出已经下载过，不可重复下载");
        }

        Integer status = ExportStatusEnum.SUCCESS.getValue();
        String errorMessage = StringUtils.EMPTY;
        try {

            blogCommentHelper.downloadCommentList(exportTask, response);

        } catch (CzzException e) {
            // 继续往外抛
            throw e;
        } catch (Exception e) {
            log.error("博客评论导出任务执行异常。message={}", e.getMessage(), e);

            status = ExportStatusEnum.FAIL.getValue();

            errorMessage = "博客评论导出任务执行失败";

            response.reset();
            response.setContentType("application/json");
            response.setCharacterEncoding("utf-8");
            try {
                response.getWriter().println(errorMessage);
            } catch (IOException ex) {
                log.error("异常结果返回输出失败。message={}", ex.getMessage());
            }
        }
        Date end = new Date();

        log.info("导出任务执行结束。执行耗时：{}毫秒", end.getTime() - start.getTime());

        ExportTaskEntity updateExportTask = new ExportTaskEntity();
        updateExportTask.setTaskId(taskId)
                .setStatus(status)
                .setStartTime(start)
                .setEndTime(end)
                .setUpdateTime(end)
                .setUpdateUser(userPo.getUsername())
                .setUpdateUserId(userPo.getUserId())
                .setRemark(errorMessage);
        exportTaskService.saveExportTask(updateExportTask);
    }


    @Transactional
    public void updateCommentLike(CommentFormVo commentFormVo) {
        UserPo userPo = SecurityUtils.getUser();

        /*
            判断博客评论是否存在
         */
        blogCommentService.existBlogComment(Collections.singletonList(commentFormVo.getCommentId()));

        /*
            获取博客信息
         */
        BlogEntity blog = blogService.getBlog(commentFormVo.getBlogId());

        int num;
        if (commentFormVo.getType().equals(CommonEnum.ZERO.getValue())) {
            /*
                点赞
             */
            userLikeCommentService.saveUserLikeComment(commentFormVo.getBlogId(), commentFormVo.getCommentId());

            num = 1;
        } else if (commentFormVo.getType().equals(CommonEnum.ONE.getValue())) {
            /*
                取消点赞
             */
            userLikeCommentService.userUnlikeComment(commentFormVo.getBlogId(), commentFormVo.getCommentId());

            num = -1;
        } else {
            throw new CzzException(ResultEnum.REQUEST_FAIL.getCode(), "操作类型不存在，请确认，如有问题，请联系管理员处理。");
        }

        if (userPo.getUserId().equals(blog.getUserId())) {
            /*
                如果是博客作者在点赞/取消点赞博客评论
             */
            blogCommentService.updateCommentLike(commentFormVo);
        }

        /*
            发送消息
         */
        // 发送一条消息到MQ中，异步更新系统博客评论的点赞数量
        BlogCommentMessage blogCommentMessage = new BlogCommentMessage(commentFormVo.getCommentId(),
                BlogCommentMessageEnum.LIKE_TYPE.getValue(), num);
        rabbitHelper.send(MqEnum.BLOG_COMMENT_LIKE, blogCommentMessage);
    }

    public void updateCommentTopFlag(CommentFormVo commentFormVo) {
        blogCommentService.updateCommentTopFlag(commentFormVo);
    }

    public void updateCommentHideFlag(CommentFormVo commentFormVo) {
        blogCommentService.updateCommentHideFlag(commentFormVo);
    }

    public void batchUpdateCommentHideFlag(List<Long> commentIdList, Integer hideFlag) {
        blogCommentService.batchUpdateCommentHideFlag(commentIdList, hideFlag);
    }
}
